-- Copyright (c) 2010, Pavel Kovar
-- All rights reserved.
--
---------------------------------------------------------------------------------------
-- This file is a part of the Witch Navigator project

-- Generates timing for universal correlator
-- Implemented
--   * 800us TIC signal
--   * Input and output register controlled
--   * ADC interface
--   * AGC detectors
--   * Signal capture controller
--   * Consecutive correlators opperation controller 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
-- library UNISIM;
-- use UNISIM.VComponents.all;


-- s1_in, s2_in are divied into real part and image part.
-- Refer to P258, 10.3.2
-- Immediate frequency signal
--  Sif,I = A * x(n) * D(n) * cos( phi(n) )
--  Sif,Q = A * x(n) * D(n) * sin( phi(n) )
-- Local oscillation from NCO
--  uos(n) = sin( phio(n) )
--  uoc(n) = cos( phio(n) )


entity cor_timing is
	 Generic (
			  tic_length : integer := 16000
			  );
	 
     Port ( clk_in : in  STD_LOGIC;
            s1_in : in  STD_LOGIC_VECTOR (7 downto 0);
            s2_in : in  STD_LOGIC_VECTOR (7 downto 0);
            clk_adc : out  STD_LOGIC;   -- 20MHz
            clk_dsp : out STD_LOGIC;
            tic : out STD_LOGIC;
            dma_ctrl : out STD_LOGIC;
            phase : out STD_LOGIC_VECTOR(2 downto 0);
            tic_page : out STD_LOGIC;
            phase_early : out STD_LOGIC_VECTOR(2 downto 0);
            tic_page_early : out STD_LOGIC;
            sr1_out : out  STD_LOGIC_VECTOR (7 downto 0);
            si1_out : out  STD_LOGIC_VECTOR (7 downto 0);
            sr2_out : out  STD_LOGIC_VECTOR (7 downto 0);
            si2_out : out  STD_LOGIC_VECTOR (7 downto 0);
            agc1 : out STD_LOGIC;
            agc2 : out STD_LOGIC;
            acq_mem_addr : out STD_LOGIC_VECTOR(13 downto 0);
            acq_mem_we : out STD_LOGIC;
            acq_mem_data : out STD_LOGIC_VECTOR(15 downto 0);
            tic_no_counter : out STD_LOGIC_VECTOR(15 downto 0);
            acq_ctr : in STD_LOGIC_VECTOR(3 downto 0)			  
        );
end cor_timing;

architecture Behavioral of cor_timing is

signal clk_dsp_pom : std_logic; -- 120Mhz
signal clk_adc_reg : std_logic;
signal tic_reg : std_logic;
signal tic_sclr : std_logic;
signal phase_pom, phase_reg : std_logic_vector(2 downto 0);
signal count_out : std_logic_vector(13 downto 0);
signal sr1_r1, si1_r1, sr2_r1, si2_r1 : std_logic_vector(7 downto 0):= (others => '0');
signal sr1_r2, si1_r2, sr2_r2, si2_r2 : std_logic_vector(7 downto 0):= (others => '0');

signal p_th: std_logic;
signal tic_page_reg, tic_page_early_reg: std_logic := '0';
signal tic_page_reg0, tic_page_reg1, tic_page_reg2: std_logic := '0';
signal tic_page_reg3, tic_page_reg4, tic_page_reg5: std_logic := '0';
signal sig_sample: std_logic;
signal dma_ctrl_pom :std_logic;
signal tic_no_counter_pom : std_logic_vector(15 downto 0) :="0000000000000000";
signal acq_d_ch1_8b : std_logic_vector(15 downto 0);
signal acq_d_ch2_8b : std_logic_vector(15 downto 0);
signal acq_d_ch12_4b_s0 : std_logic_vector(15 downto 0);
signal acq_d_ch12_4b_s1 : std_logic_vector(15 downto 0);
signal acq_d_ch12_4b_s2 : std_logic_vector(15 downto 0);
signal acq_d_ch12_4b_s3 : std_logic_vector(15 downto 0);

component clk_dds
port
 (-- Clock in ports
  CLK_IN1           : in     std_logic;
  -- Clock out ports
  CLK_OUT1          : out    std_logic
 );
end component;

component phase_counter
	port (
	clk: IN std_logic;
	thresh0: OUT std_logic;
	q: OUT std_logic_VECTOR(2 downto 0));
end component;

component tic_counter
	port (
	clk: IN std_logic;
	ce: IN std_logic;
	sclr: IN std_logic;
	q: OUT std_logic_VECTOR(13 downto 0));
end component;

begin

-- PLL 6x (120 MHz)
    clk_dds1 : clk_dds
    port map
    (-- Clock in ports
        CLK_IN1            => clk_in,
    -- Clock out ports
        CLK_OUT1           => clk_dsp_pom);

    -- computation phase generator
    phase_count : phase_counter
    port map (
                 clk => clk_dsp_pom,
                 thresh0 => p_th,
                 q => phase_pom);

    -- correlator tic counter
    tic_count: tic_counter
    port map (
                 clk => clk_dsp_pom,
                 ce => p_th,
                 sclr => tic_sclr,
                 q => count_out);

    process(clk_dsp_pom)
    begin
        if clk_dsp_pom'event and clk_dsp_pom = '1' then
            if count_out = CONV_STD_LOGIC_VECTOR(tic_length-1, 14) and p_th = '1' then
                tic_sclr <= '1';    -- at current clk_dsp_pom cycle, count_out = 160000,
                                    -- next clk_dsp_pom cycle, count_out = 0.
                tic_no_counter_pom <= tic_no_counter_pom+1; --tic number counter
            else
                tic_sclr <= '0';
            end if;
        end if;
    end process;

    process(clk_dsp_pom)
    begin
        if clk_dsp_pom'event and clk_dsp_pom = '1' then
            phase_reg <= phase_pom;
            if count_out = CONV_STD_LOGIC_VECTOR(tic_length-1, 14) then 
                tic_reg <= '1';
            else
                tic_reg <= '0';
            end if;
            if count_out = CONV_STD_LOGIC_VECTOR(0, 14) then 
                dma_ctrl_pom <= '1'; -- zacatek DMA z FPGA do PC
            elsif count_out = CONV_STD_LOGIC_VECTOR(tic_length-1000, 14) then
                dma_ctrl_pom <= '0'; -- sestupna hrana 
            end if;	

            if count_out = CONV_STD_LOGIC_VECTOR(tic_length-2, 14) and phase_reg ="100" then -- N-2
                tic_page_early_reg <= not tic_page_early_reg;
            end if;
            tic_page_reg0 <= tic_page_early_reg;			
            tic_page_reg1 <= tic_page_reg0;
            tic_page_reg2 <= tic_page_reg1;
            tic_page_reg3 <= tic_page_reg2;
            tic_page_reg4 <= tic_page_reg3;
            tic_page_reg5 <= tic_page_reg4;
            tic_page_reg <= tic_page_reg5;
        -- adc_clk generation and ADC sampeing
            if phase_reg = "101" then
                sr1_r1 <= s1_in;
                sr2_r1 <= s2_in;
                clk_adc_reg <= '0';
            end if;
            if phase_reg = "010" then
                si1_r1 <= s1_in;
                si2_r1 <= s2_in;
                clk_adc_reg <= '1';
            end if;

        -- adc resample one clk_dsp cycle before frame begining
        -- signal is registered in cor_mac block
        -- timing improvement
        -- ADC sample transformation from direct shift code to the second complement
            if phase_reg = "100" then
                sr1_r2(6 downto 0) <= sr1_r1(6 downto 0);
                sr1_r2(7) <= not sr1_r1(7);
                si1_r2(6 downto 0) <= si1_r1(6 downto 0);
                si1_r2(7) <= not si1_r1(7);
                sr2_r2(6 downto 0) <= sr2_r1(6 downto 0);
                sr2_r2(7) <= not sr2_r1(7);
                si2_r2(6 downto 0) <= si2_r1(6 downto 0);
                si2_r2(7) <= not si2_r1(7);
            end if;
        end if;
    end process;

    dma_ctrl <= dma_ctrl_pom;
    clk_adc <= clk_adc_reg;
    phase <= phase_reg;
    phase_early <= phase_pom;
    tic <= tic_reg;
    clk_dsp <= clk_dsp_pom;
    tic_page <= tic_page_reg;
    tic_page_early <= tic_page_early_reg;

    sr1_out <= sr1_r2;
    si1_out <= si1_r2;
    sr2_out <= sr2_r2;
    si2_out <= si2_r2;


    acq_mem_we <= '1' when phase_reg = "011" else '0';
    acq_mem_addr <= count_out;

-- acquisition memory multiplexer
-- channel 1, 8 bits
    acq_d_ch1_8b(7 downto 0) <= sr1_r2;
    acq_d_ch1_8b(15 downto 8) <= si1_r2;
-- channel 2, 8 bits
    acq_d_ch2_8b(7 downto 0) <= sr2_r2;
    acq_d_ch2_8b(15 downto 8) <= si2_r2;
-- both channels, 4 bits, shoft 0
    acq_d_ch12_4b_s0(3 downto 0) <= sr1_r2(7 downto 4);
    acq_d_ch12_4b_s0(7 downto 4) <= si1_r2(7 downto 4);
    acq_d_ch12_4b_s0(11 downto 8) <= sr2_r2(7 downto 4);
    acq_d_ch12_4b_s0(15 downto 12) <= si2_r2(7 downto 4);
-- both channels, 4 bits, shoft 1
    acq_d_ch12_4b_s1(3 downto 0) <= sr1_r2(6 downto 3);
    acq_d_ch12_4b_s1(7 downto 4) <= si1_r2(6 downto 3);
    acq_d_ch12_4b_s1(11 downto 8) <= sr2_r2(6 downto 3);
    acq_d_ch12_4b_s1(15 downto 12) <= si2_r2(6 downto 3);
-- both channels, 4 bits, shoft 2
    acq_d_ch12_4b_s2(3 downto 0) <= sr1_r2(5 downto 2);
    acq_d_ch12_4b_s2(7 downto 4) <= si1_r2(5 downto 2);
    acq_d_ch12_4b_s2(11 downto 8) <= sr2_r2(5 downto 2);
    acq_d_ch12_4b_s2(15 downto 12) <= si2_r2(5 downto 2);
-- both channels, 4 bits, shoft 3
    acq_d_ch12_4b_s3(3 downto 0) <= sr1_r2(4 downto 1);
    acq_d_ch12_4b_s3(7 downto 4) <= si1_r2(4 downto 1);
    acq_d_ch12_4b_s3(11 downto 8) <= sr2_r2(4 downto 1);
    acq_d_ch12_4b_s3(15 downto 12) <= si2_r2(4 downto 1);

    acq_mem_data <= acq_d_ch1_8b     when acq_ctr(3 downto 2) = "10" else
                    acq_d_ch2_8b     when acq_ctr(3 downto 2) = "11"  else
                    acq_d_ch12_4b_s0 when (acq_ctr(3) = '0' and acq_ctr(1 downto 0) = "00") else 
                    acq_d_ch12_4b_s1 when (acq_ctr(3) = '0' and acq_ctr(1 downto 0) = "01") else
                    acq_d_ch12_4b_s2 when (acq_ctr(3) = '0' and acq_ctr(1 downto 0) = "10") else 
                    acq_d_ch12_4b_s3 when (acq_ctr(3) = '0' and acq_ctr(1 downto 0) = "11") else
                    acq_d_ch1_8b;

    tic_no_counter <= tic_no_counter_pom;

-- agc diskciminator 
    agc1 <= '1' when ((sr1_r2(7 downto 5) = "000") or (sr1_r2(7 downto 5) = "111")) else '0'; 
    agc2 <= '1' when ((sr2_r2(7 downto 5) = "000") or (sr2_r2(7 downto 5) = "111")) else '0';

end Behavioral;

